<template>
  <div class="container">
    <div class="content">
      <div class="elTreeClass">
        <button @click="handleButtonClick">点击按钮</button>
        <el-tree
          ref="tree"
          :data="treeData"
          node-key="nodePath"
          :props="defaultProps"
          highlight-current
          default-expand-all
          show-checkbox
          :check-strictly="false"
          :expand-on-click-node="false"
          :render-content="renderContent"
          @check="handleCheck"
          @node-click="handleNodeClick"
        >
        </el-tree>

      </div>
      <div class="transfer-buttons">
        <el-button  @click="moveToRight">></el-button>
      </div>
      <div class="elTableClass">
        <el-button @click="handleSubmit">提交</el-button>
      <el-table
          :data="tableDataFinal"
          style="width: 100%"
          :row-key="idKey"
          :default-expand-all="true"
          border
        >
        <el-table-column prop="name" label="参数名称">
          <template v-slot="scope">
            <span
              :style="{ color: rightMap[scope.row.nodePath] ? 'red' : 'inherit' }"
            >
              {{ scope.row.name }}
              <span v-if="rightMap[scope.row.nodePath]">
                （{{ rightMap[scope.row.nodePath].incompatibleDsc }}）
              </span>
            </span>
          </template>
        </el-table-column>
        <el-table-column
          v-for="(col, index) in columns"
          :key="index"
          :prop="col.prop"
          :label="col.label"
          :show-overflow-tooltip="true"
        >
          <template v-slot="{ row }">
            <el-input v-if="col.type === 'input'" v-model="row[col.prop]"></el-input>
            <el-checkbox 
              v-else-if="col.type === 'checkbox'" 
              v-model="row[col.prop]"
              :true-label="1"
              :false-label="0"
              :disabled="!!row.initialDisabled"
              ></el-checkbox>
            <el-select v-else-if="col.type === 'select' && col.prop === 'fillRule'" v-model="row[col.prop]" placeholder="请选择">
              <el-option
                v-for="item in fillRuleList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
            <el-select v-else-if="col.type === 'select' && col.prop === 'checkRule'" v-model="row[col.prop]" placeholder="请选择">
              <el-option
                v-for="item in checkRuleList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              ></el-option>
            </el-select>
            <span v-else>{{ row[col.prop] }}</span>
          </template>
        </el-table-column>
        
      </el-table>
      <div>
        <h3>当前的数据</h3>
        <pre>{{ tableData }}</pre>
      </div>
      <div>反显的数据</div>
      <pre>{{ tableDataFinal }}</pre>
      </div>
    </div>
  </div>
</template>

<script>
import cloneDeep from 'lodash/cloneDeep';
export default {
  name: 'checkBoxDemo',
  data() {
    return {
      incompatibleFromBack:[
        {
          incompatibleDsc:'参数（child1）字段类型不兼容',
          paraNodePath:'parent.child1',
        },
        {
          incompatibleDsc:'参数（child2）字段类型不兼容',
          paraNodePath:'parent.child2.child2-1',
        },
      ],//后端返回的数据
      // BackMap: {
      //   'parent.child1': {
      //     incompatibleDsc:'参数（child1）字段类型不兼容',
      //   },
      //   'parent.child2': {
      //     incompatibleDsc:'参数（child2）字段类型不兼容',
      //   },
      // },
      BackMap:{},//后端返回的数据
      leftMap: {},//左侧不兼容数据
      rightMap: {},//右侧不兼容数据
      defaultProps: {
        children: 'children',//指定子节点属性名
        label: 'name',// 指定节点标签的属性名
        checked: 'checked',
        code: 'code',
        type:'type',
      },
      treeData: [
        {
          nodePath:'parent',
          code: 'parent',
          name: 'request标识',
          type: 'object',
          required: '1',
          children: [
            {
              nodePath:'parent.child1',
              code: 'child1',
              name: 'child1不兼容1',
              required: '0',
              type: 'string',
              children: null,
            },
            {
              nodePath:'parent.child2',
              code: 'child2',
              name: 'child2',
              required: '0',
              type: 'string',
              children: [
                {
                  nodePath:'parent.child2.child2-1',
                  code: 'child2-1-不兼容数据',
                  name: 'child2-1',
                  required: '0',
                  type: 'string',
                  children: null,
                  parentId: 'child2'
                },
                {
                  nodePath:'parent.child2.child2-2',
                  code: 'child2-2',
                  name: 'child2-2',
                  required: '0',
                  type: 'string',
                  children: null,
                  parentId: 'child2'
                },
                {
                  nodePath:'parent.child2.child2-3',
                  code: 'child2-3',
                  name: 'child2-3',
                  required: '0',
                  type: 'string',
                  children: null,
                  parentId: 'child2'
                }
              ],
            },
            {
              nodePath:'parent.child3',
              code: 'child3',
              name: 'child3',
              required: '0',
              type: 'string',
              children: [
                {
                  nodePath:'parent.child3.child3-1',
                  code: 'child3-1',
                  name: 'child3-1',
                  required: '1',
                  type: 'string',
                  children: [
                    {
                      nodePath:'parent.child3.child3-1.child3-1-1',
                      code: 'child3-1-1',
                      name: 'child3-1-1',
                      required: '1',
                      type: 'string',
                      children: null,
                      parentId: 'child3-1',
                    }
                  ],
                }
              ],
            },
            {
              nodePath:'parent.child4',
              code: 'child4',
              name: 'child4',
              required: '0',
              type: 'string',
              children: null,
            }
          ],
        }
      ],
      selectedNodes: [], // 存储选中的节点数据
      tableData:[],//右侧表格的数据
      fillRuleList:[{ value: '1', label: '规则A' }, { value: '2', label: '规则B' }],//填充规则数据
      checkRuleList:[{ value: '1', label: '规则1' }, { value: '2', label: '规则2' }],//校验规则数据

      tableDataFinal:[],//右侧表格的数据
      columns: [
        { prop: 'name', label: '参数名称', type: 'text' },
        { prop: 'required', label: '必填', type: 'checkbox' , width: 55,
          render: (h, params) => {
            console.log('row',params.row);
            const row = params.row;
            return h('el-checkbox', {
              props: {
                modelValue: row.required === 1, // 根据 required 属性值设置复选框的选中状态
                disabled: row.required === 1 // 如果是必填字段，则禁用复选框
              },
              on: {
                change: (value) => {
                  this.handleCheckboxChange(row, value);
                }
              }
            });
          }
        },
        { prop: 'maxLen', label: '最大长度', type: 'input'},
        { prop: 'checkRule', label: '校验规则', type: 'select'},
        { prop: 'fillRule', label: '填充规则', type: 'select', options: [{ value: '1', label: '规则1' }, { value: '2', label: '规则2' }] },
        { prop: 'fillValue', label: '填充内容', type: 'input' }
      ],
      idKey: 'nodePath',

      leftBoxWidth:0,
      tooltipText: '',
      showTooltip: false,
      currentTooltipNode: null,//记录当前节点
      tooltipPosition: { x: 0, y: 0 },
      newTree: [],
      isVisit : {},
      ret: {},
      visitObj: {},
      newTree: {},
    }
  },
  methods: {
    //TODO selectedKeys没有怎么办？右侧存在存量数据，提交提交
    processSelectedNodes(selectedKeys) {
      // 创建一个新的数组，用于存储新的表格数据
      const newTableData = [];

      // 遍历 selectedKeys，处理左侧树中被勾选的节点
      selectedKeys.forEach(nodePath => {
        // 将节点添加到新的表格数据中
        const nodeData = this.findNodeByPath(this.treeData, nodePath);
        if (nodeData) {
          newTableData.push(nodeData);
        }
      });
      // 保留右侧表格的原有数据，并添加新选择的数据
      this.tableDataFinal = this.tableDataFinal.filter(item => selectedKeys.has(item.nodePath)).concat(newTableData);
      console.log('this.tableDataFinal----数据', this.tableDataFinal );
      
      // 更新视图
      this.$forceUpdate();
    },
  // 根据 nodePath 查找节点数据
  findNodeByPath(tree, path) {
    const pathParts = path.split('.');
    let currentNodes = tree;
    let foundNode = null;
    for (let i = 0; i < pathParts.length; i++) {
      const part = pathParts[i];
      foundNode = currentNodes.find(node => node.nodePath === part);
      if (!foundNode) {
        return null;
      }
      if (foundNode.children && foundNode.children.length > 0) {
        currentNodes = foundNode.children;
      } else if (i < pathParts.length - 1) {
        return null;
      }
    }
    return foundNode;
  },
  // 获取左侧树中被勾选的节点的 nodePath 集合

    logData(data) {
      console.log('Tree node data:', data);
    },
    // 按钮点击事件处理函数--通过这里去模拟数据
    handleButtonClick() {
      // 这里调用您需要模拟的函数
      this.simulateFunction();
    },
    // 您要模拟调用的函数
    simulateFunction() {
      // 执行您的逻辑，如更新树形结构等
      console.log('按钮已点击，调用模拟函数');

      // 第一步：生成 BackMap
      this.incompatibleFromBack.forEach(item => {
        this.BackMap[item.paraNodePath] = {
          incompatibleDsc: item.incompatibleDsc,
        };
      });
      console.log(`BackMap:`, this.BackMap);
      // {
      //     "parent.child1": {
      //         "incompatibleDsc": "参数（child1）字段类型不兼容"
      //     },
      //     "parent.child2": {
      //         "incompatibleDsc": "参数（child2）字段类型不兼容"
      //     }
      // }
      // 第二步：匹配右侧表格数据
      this.matchIncompatibilityInTable();

    },

    // 匹配右侧表格中的不兼容数据
    matchIncompatibilityInTable() {
      // 初始化 leftMap 和 rightMap
      this.leftMap = { ...this.BackMap }; // 复制 BackMap
      this.rightMap = {};

      // 递归匹配函数
      const matchIncompatibility = (data) => {
        data.forEach(item => {
          const nodePath = item.nodePath;
          if (this.leftMap[nodePath]) {
            // 匹配成功
            this.rightMap[nodePath] = this.leftMap[nodePath];
            delete this.leftMap[nodePath];
          }
          // 递归处理子节点
          if (item.children && item.children.length > 0) {
            matchIncompatibility(item.children);
          }
        });
      };

      // 开始匹配
      matchIncompatibility(this.tableDataFinal);
      console.log(`leftMap:`, this.leftMap);
      //leftMap: {
      //     "parent.child2": {
      //         "incompatibleDsc": "参数（child2）字段类型不兼容"
      //     }
      // }
      console.log(`rightMap:`, this.rightMap);
      // {
      //     "parent.child1": {
      //         "incompatibleDsc": "参数（child1）字段类型不兼容"
      //     }
      // }
    },
    // updateContainerHeight() {
    //   const container = this.$refs.container;
    //   const content = this.$refs.content;

    //   // 更新容器的高度
    //   container.style.height = `${content.scrollHeight}px`;
    // },
    // 渲染节点内容
    // 使用一个单独的数据属性来记录当前悬停的元素。
    // 在 mouseover 和 mouseout 事件中更新这个数据属性。
    // 在 CSS 中使用动态类来控制 tooltip 的显示
  renderContent(h, { node, data, store }) {
    // 判断是否显示tooltip
    const tooltipElement = this.currentTooltipNode === node ? (
      h('span', 
        { 
          class: ['tooltip', { 'show-tooltip': this.showTooltip}],
          style: {
            backgroundColor: '#f00',
            left: `${this.tooltipPosition.x}px`,
            top: `${this.tooltipPosition.y}px`,
          },
        }, this.tooltipText)
      ) : null;

    // 判断节点是否在 leftMap 中有不兼容信息
    const incompatibleInfo = this.leftMap[data.nodePath];
    // 设置文本颜色，如果存在不兼容，则标红
    const textColor = incompatibleInfo ? 'red' : 'inherit';
    // vue模版语法
    return h(
      'span',
      null,
      [
        data.required === '1' && h('span',{ style: { color: 'red', marginLeft: '5px', marginRight: '5px' } }, '*'),
        data.code && h('span', { style: { color: textColor } }, `${data.code} `),
        h(
          'span',
          {
              class: 'ellipsis',
              style: { color: textColor },
              on: {
                mouseover: (event) => this.handleShowTooltip(event, node, data.name),
                mouseout: () => this.handleHideTooltip(),
              },
          },
          [
            data.name, 
            // 显示不兼容描述
            incompatibleInfo 
              ? h('span', { style: { color: 'red', marginLeft: '5px' } }, `（${incompatibleInfo.incompatibleDsc}）`) 
              : null,
            tooltipElement
          ]
        ),
        data.type && h('span', { style: { color: textColor } }, ` (${data.type})`)
      ].filter(Boolean)
    )
  },
  // TODO 浮动有bug
  handleShowTooltip(event,node,name) {
    this.tooltipText = name;
      // 获取左侧属性盒子的宽度
      const tooltipWidth = 300; // 假设 tooltip 宽度为 200px
      const tooltipHeight = 30; // 假设 tooltip 高度为 30px

      // 获取父级元素相对于视口的位置
      const treeContainer = this.$refs.tree.$el;
      const treeRect = treeContainer.getBoundingClientRect();

      // 计算相对于父级元素的坐标
      const x = Math.round(event.clientX - treeRect.left);
      const y =Math.round(event.clientY - treeRect.top - 20); // 初始 Y 坐标，假设 tooltip 显示在上方

      // console.log('x',x);
      // console.log('y',y);
      // console.log('‘leftBoxWidth', this.leftBoxWidth);

      if (x + tooltipWidth  > this.leftBoxWidth) {
        // 如果 tooltip 放在右侧会超出容器宽度，则放在下方
        this.tooltipPosition = { x: x , y: y+ tooltipHeight };
      } else {
        this.tooltipPosition = { x: x, y: y };
      }
      // console.log('this.tooltipPosition',this.tooltipPosition);
      
    this.currentTooltipNode = node;
    this.showTooltip = true;
  },
  handleHideTooltip() {
      this.currentTooltipNode = null;
      this.showTooltip = false;
  },
  handleNodeClick(node) {
    // console.log('节点点击事件----------1:', node);
  },
  handleCheck() {
    const checkedNodes = this.$refs.tree.getCheckedNodes();
    console.log('checkedNodes1111111111', checkedNodes);
    
    const selectedKeys = new Set(checkedNodes.map(node => node.nodePath));
    console.log('selectedKeys',selectedKeys);
    
    // 深拷贝 treeData
    const treeDataCopy = cloneDeep(this.treeData);
    // 创建新的表格数据，只包括选中的节点
    const newTableData = this.createTableDataFromKeys(treeDataCopy, selectedKeys);
    // console.log('newTableData',newTableData);
    this.tableData = newTableData

 





    // 更新表格数据后期维护
    // this.tableData = this.mergeTableData(this.tableData, newTableData, selectedKeys);
    // console.log('Updated tableData with new fields and structure:', this.tableData);
  },
  hasSelectedChildren(children, selectedKeys) {
    return children.some(child => selectedKeys.has(child.nodePath) || (child.children && this.hasSelectedChildren(child.children, selectedKeys)));
  },
  createTableDataFromKeys(nodes, selectedKeys) {
    const result = [];
    nodes.forEach(node => {
      if (selectedKeys.has(node.nodePath) || (node.children && this.hasSelectedChildren(node.children, selectedKeys))) {
        // 添加节点数据
        const tableNode = {
          nodePath: node.nodePath,
          name: node.name,
          required: Number(node.required),// 将字符串转换为数字
          initialDisabled: Number(node.required), // 根据 required 字段设置 initialDisabled
          maxLen: node.maxLen || '', // 默认值或根据实际需求设置
          checkRule: node.checkRule || '', // 默认值或根据实际需求设置
          fillRule: node.fillRule || '', // 默认值或根据实际需求设置
          fillValue:  node.fillValue || '', // 默认值或根据实际需求设置
          children: null // 初始化子节点
        };

        // 添加子节点
        if (node.children) {
          tableNode.children = this.createTableDataFromKeys(node.children, selectedKeys);
        }

        result.push(tableNode);
      }
    });

    return result;
  },
  mergeTableData(existingData, newData, selectedKeys) {
  const existingDataMap = new Map(existingData.map(item => [item.nodePath, item]));
  newData.forEach(newItem => {
    if (existingDataMap.has(newItem.nodePath)) {
      const existingItem = existingDataMap.get(newItem.nodePath);
      // 保留现有数据的内容
      Object.assign(existingItem, newItem, {
        maxLen: existingItem.maxLen,
        checkRule: existingItem.checkRule,
        fillRule: existingItem.fillRule,
        fillValue: existingItem.fillValue,
      });
      if (newItem.children && existingItem.children) {
        existingItem.children = this.mergeTableData(existingItem.children, newItem.children);
      }
    } else {
      existingData.push(newItem);
    }
  });
  // 移除未选中的节点
  return existingData.filter(item => newData.some(newItem => newItem.nodePath === item.nodePath) || selectedKeys.has(item.nodePath));
  },
  // 移动到右边
  // 1、点击二次确认
  // 完全替换
  moveToRight() {
    // 获取被勾选的节点的 nodePath 集合
      this.$alert('请手动点击生成表格按钮以更新右侧表格，注意生成会替换当前数据', '提示', {
        confirmButtonText: '确定',
        type: 'warning'
      })
      .then(() => {


      const checkedNodes = this.$refs.tree.getCheckedNodes();
      const selectedKeys = new Set(checkedNodes.map(node => node.nodePath));
      console.log('selectedKeys',selectedKeys);

      // 调用 processSelectedNodes 方法处理被勾选的节点
      this.processSelectedNodes(selectedKeys);






      // 遍历 selectedNodePaths，处理 leftMap 和 rightMap
        selectedKeys.forEach(nodePath => {
        // 从 leftMap 中删除
        if (this.leftMap[nodePath]) {
          this.$delete(this.leftMap, nodePath);
        }
        // 从 rightMap 中删除
        if (this.rightMap[nodePath]) {
          this.$delete(this.rightMap, nodePath);
        }
      });


      // 更新视图
      this.$forceUpdate();
        this.tableDataFinal = this.tableData;
      });
    
  },
  // 根据 nodePath 查找节点数据
  findNodeByPath(tree, path) {
    const pathParts = path.split('.');
    let currentNodes = tree;
    let foundNode = null;
    for (let i = 0; i < pathParts.length; i++) {
      const part = pathParts[i];
      foundNode = currentNodes.find(node => node.nodePath === part);
      if (!foundNode) {
        return null;
      }
      if (foundNode.children && foundNode.children.length > 0) {
        currentNodes = foundNode.children;
      } else if (i < pathParts.length - 1) {
        return null;
      }
    }
    return foundNode;
  },
  getLeftBoxWidth() {
      const leftBox = document.querySelector('.elTreeClass');
      this.leftBoxWidth = leftBox.offsetWidth;
      // console.log('Left Box Width:', this.leftBoxWidth);
  },
  // 处理右边table
    handleCheckboxChange(row, value) {
      console.log(`Row ${row.id} checkbox changed to: ${value}`);
      row.required = value ? '1' : '0';
    },
    getInformForView(){
      let data = {
        viewInfo:[
          {
            nodePath: "parent",
            name: "request标识",
            required: "1",
            maxLen: "1",
            checkRule: "1",
            fillRule: "2",
            fillValue: "111111111",
            children: [
              {
                nodePath: "parent.child1",
                name: "我是child1我是child1我是child1我是child1我是child1",
                required: "0",
                maxLen: "2",
                checkRule: "1",
                fillRule: "2",
                fillValue: "AAAAAAAAAAAA",
                children: null
              }
            ]
          }
        ]
      }
      this.tableDataFinal = this.convertRequiredField(data.viewInfo);
      console.log('this.tableDataFinal----------1',this.tableDataFinal);
      
    },
    // 将返回的数据的require改为数字的 0 和 1
    convertRequiredField(data) {
      return data.map(node => {
        return {
          ...node,
          required: Number(node.required), // 将字符串转换为数字
          initialDisabled: node.required == 1, // 根据 required 字段设置 initialDisabled
          children: node.children ? this.convertRequiredField(node.children) : null
        };
      });
    },
    // 处理提交
    async handleSubmit() {
      const dataToSubmit = this.tableDataFinal.map(row => {
        return {
          ...row,
          required: String(row.required) // 将 required 转换为数字
        };
      });
      console.log('提交的数据:', dataToSubmit);
      // 在这里执行提交操作，例如发送请求到后端


      // 提交右侧表格数据，假设后端返回新的不兼容数据
      try {
      // 提交右侧表格数据，假设后端返回新的不兼容数据
      const response = await this.submitTableData(this.tableDataFinal);
      const newIncompatibleData = response.data;

      // 将新的不兼容数据转换为 BackMap
      const BackMap = {};
      newIncompatibleData.forEach(item => {
        BackMap[item.paraNodePath] = {
          incompatibleDsc: item.incompatibleDsc,
        };
      });

      // 初始化 leftMap 和 rightMap
      this.leftMap = { ...BackMap };
      this.rightMap = {};

      // 优先在右侧表格中匹配和展示不兼容数据
      this.matchIncompatibilityInTable();

      // 更新视图
      this.$forceUpdate();
    } catch (error) {
      console.error('提交失败:', error);
    }
    },
    // 模拟提交右侧表格数据的方法
    submitTableData(data) {
      // 返回一个 Promise，模拟后端交互
      return new Promise((resolve, reject) => {
        // 模拟后端处理，延迟 1 秒
        setTimeout(() => {
          // 模拟后端返回新的不兼容数据
          const newIncompatibleData = [
            {
              incompatibleDsc: '参数（child1）字段类型不兼容',
              paraNodePath: 'parent.child1',
            },
            {
              incompatibleDsc: '参数（child2）字段类型不兼容',
              paraNodePath: 'parent.child2.child2-1',
            },
            {
              incompatibleDsc: '参数（child2-2）字段类型不兼容',
              paraNodePath: 'parent.child2.child2-2',
            },
          ];
          resolve({ data: newIncompatibleData });
        }, 1000);
      });
    },





    updateTreeSelection() {
      const selectedKeysNodes = this.extractNodePaths(this.tableDataFinal);
      // const selectedKeys = new Set(this.tableDataFinal.map(item => item.nodePath));
      console.log('selectedKeysNodes',selectedKeysNodes);      
      this.$nextTick(() => {
        selectedKeysNodes.forEach(nodePath => {
          const node = this.$refs.tree.getNode(nodePath);
          if (node) {
            node.setChecked(true, false); // 第二个参数 false 表示不递归选中子节点
          }
        });
      });
    },
    extractNodePaths(data) {
      let nodePaths = [];
      data.forEach(item => {
        nodePaths.push(item.nodePath);
        if (item.children) {
          nodePaths = nodePaths.concat(this.extractNodePaths(item.children));
        }
      });
      return nodePaths;
    }
  },
  mounted() {
    // this.updateContainerHeight();
    // new MutationObserver(this.updateContainerHeight).observe(
    //   this.$refs.content,
    //   {
    //     childList: true,
    //     subtree: true
    //   }
    // );
    this.getLeftBoxWidth();
    this.updateTreeSelection();
  },
  created() {
    // created 钩子中使用 bind 方法来确保 showTooltip 和 hideTooltip 方法绑定到组件实例
    this.handleShowTooltip = this.handleShowTooltip.bind(this)
    this.handleHideTooltip = this.handleHideTooltip.bind(this);
    // TODO 每个节点加一个id




    // 模拟查看接口获取数据
    this.getInformForView();
  },


  // 
}
</script>

<style lang="less">
  .container {
    width: 100%; /* 容器宽度设为 100% 或者具体数值 */
    max-width: 100%; /* 最大宽度设为 100%，防止过宽 */
    overflow-y: auto; /* 当内容超过容器高度时，出现垂直滚动条 */
    height: 100vh; /* 高度设为视口高度，可以根据需要调整 */
  /* 自定义滚动条样式 */
    scrollbar-width: thin; /* Firefox */
    &::-webkit-scrollbar { /* Chrome, Safari, and Edge */
      width: 8px; /* 滚动条宽度 */
    }
    &::-webkit-scrollbar-track {
      background: #f1f1f1; /* 轨道背景颜色 */
    }
    &::-webkit-scrollbar-thumb {
      background: #888; /* 滚动条颜色 */
    }
    &::-webkit-scrollbar-thumb:hover {
      background: #555; /* 滚动条悬停颜色 */
    }
  }
  .content {
    display: flex; /* 使用 Flex 布局 */
    // flex-wrap: wrap; 
    gap: 1rem; /* 子元素之间的间距 */
  }
  .elTreeClass {
    flex: 1;
    // TODO新加的
    position: relative;
    background-color: lightblue;
  }
  .transfer-buttons {
    display: flex;
    flex-direction: column;
    // justify-content: center;
    align-items: center;
  }
  .transfer-buttons .el-button {
    margin: 5px 0;
  }
  .transfer-buttons .el-button:hover {
    background-color: orange; /* 按钮悬停时的颜色 */
    color: white; /* 按钮悬停时的文字颜色 */
  }
  .elTableClass {
    flex: 2; /* 占据 2 份空间 */
    background-color: lightgreen;
  }
  .el-tree {
    scrollbar-width: thin; /* Firefox */
    &::-webkit-scrollbar { /* Chrome, Safari, and Edge */
    width: 8px; /* 滚动条宽度 */
  }
  &::-webkit-scrollbar-track {
    background: #f1f1f1; /* 轨道背景颜色 */
  }
  &::-webkit-scrollbar-thumb {
    background: #888; /* 滚动条颜色 */
  }
  &::-webkit-scrollbar-thumb:hover {
    background: #555; /* 滚动条悬停颜色 */
  }
  .ellipsis {
    display: inline-block;
    max-width: 180px; /* 可以根据需要调整 */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: top;
  }

  .tooltip {
    position: absolute;
    background-color: #dcdfe6;
    color: #fff;
    border-radius: 4px;
    z-index: 1000;
    visibility: hidden;
  }

  .show-tooltip {
    visibility: visible;
  }
}
</style>